package drds.plus.executor.cursor.cursor.impl.common;

import drds.plus.executor.ExecuteContext;
import drds.plus.executor.cursor.cursor.IRangeCursor;
import drds.plus.executor.cursor.cursor.ISortingCursor;
import drds.plus.executor.cursor.cursor.impl.SortingCursor;
import drds.plus.executor.record_codec.record.KeyValueRecordPair;
import drds.plus.executor.record_codec.record.Record;
import drds.plus.executor.row_values.RowValues;
import drds.plus.executor.row_values.row_value.RowValueScaners;
import drds.plus.executor.utils.Utils;
import drds.plus.sql_process.abstract_syntax_tree.configuration.ColumnMetaData;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Filter;
import drds.plus.util.GeneralUtil;
import lombok.Getter;
import lombok.Setter;

import java.util.Comparator;
import java.util.List;

/**
 * 现在具有对多个索引内前缀字段+非前缀字段
 */
public class RangeCursor extends SortingCursor implements IRangeCursor {
    /**
     * 范围，从哪里开始？
     */
    @Setter
    @Getter
    protected RowValues from;
    /**
     * 范围，到哪里结束
     */
    @Setter
    @Getter
    protected RowValues to;
    @Setter
    @Getter
    protected Comparator<RowValues> fromComparator;
    @Setter
    @Getter
    protected Comparator<RowValues> toComparator;
    //
    @Setter
    @Getter
    protected ExecuteContext executeContext;
    @Setter
    @Getter
    boolean first = true;//理想情况是起点是from 终点是to,to的next就是from(firstInNewCursor),from的pre就是to(last())
    @Setter
    @Getter
    private boolean comparatorInited = false;
    @Setter
    @Getter
    private Filter filter = null;

    public RangeCursor(ExecuteContext executeContext, ISortingCursor cursor, Filter filter) throws RuntimeException {
        super(cursor, null, cursor.getOrderByList());
        this.executeContext = executeContext;
        this.filter = filter;
        Range range = new RangeMaker().makeRange(filter, orderByList);
        this.from = range.from;
        this.to = range.to;
    }

    /**
     * next和pre方法不会进行[from to]内循环,只要底层的游标取不到值那么就不再找了
     */
    public RowValues next() {
        if (cursor == null) {
            return null;
        }
        RowValues rowData = null;
        if (first) {
            first = false;
            rowData = first();
            if (rowData == null) {
                return null;
            }
        } else {
            rowData = cursor.next();
        }
        if (rowData == null) {
            return null;
        }
        if (match(rowData)) {
            return rowData;
        } else {
            return null;
        }

    }

    public RowValues prev() {
        RowValues rowData;
        if (first) {
            first = false;
            rowData = last();
            if (rowData == null) {
                return null;
            }
        } else {
            rowData = parentCursorPrev();
        }
        if (rowData == null) {
            return null;
        }
        if (match(rowData)) {
            return rowData;
        } else {
            return null;
        }

    }

    /**
     * @return true 如果符合区间。false 如果不符合区间
     */
    private boolean match(RowValues rowData) {
        initComparator(rowData);
        int result = fromComparator.compare(from, rowData);
        if (result == 0) {// equal;
            return true;
        } else if (result > 0) {//from>rowData value
            return false;
        } else {//from<rowData value[大于from]
            result = toComparator.compare(to, rowData);
            if (result == 0) {// equal;
                return true;
            } else {
                //to>rowData value
                return result >= 0;

            }
        }
    }

    private void initComparator(RowValues rowData) {
        if (comparatorInited) {
            return;
        }
        comparatorInited = true;
        //
        List<ColumnMetaData> columnMetaDataList = to.getParentCursorMetaData().getColumnMetaDataList();
        List<Item> itemList = Utils.getIColumnsWithISelectable(columnMetaDataList.toArray(new ColumnMetaData[0]));
        fromComparator = RowValueScaners.getComparator(from.getParentCursorMetaData(), itemList, rowData.getParentCursorMetaData(), itemList);
        toComparator = RowValueScaners.getComparator(to.getParentCursorMetaData(), itemList, rowData.getParentCursorMetaData(), itemList);

    }

    public boolean skipTo(Record keyRecord) throws RuntimeException {
        if (parentCursorSkipTo(keyRecord)) {
            RowValues rowData = current();
            return match(rowData);
        }
        return false;
    }

    public boolean skipTo(KeyValueRecordPair keyKeyValueRecordPair) throws RuntimeException {
        return skipTo(keyKeyValueRecordPair.getKey());
    }
    /**
     * ========================================================================================================================================================================================================
     * firstInNewCursor last核心处理逻辑
     * ========================================================================================================================================================================================================
     */
    /**
     * from作为起点
     */
    public RowValues first() throws RuntimeException {
        this.first = false;
        RowValues rowData = from;
        Record record = Utils.convertToRecord(rowData);
        if (!cursor.skipTo(record)) {
            return null;
        } else {
            return cursor.current();
        }
    }

    public RowValues last() throws RuntimeException {
        first = false;
        RowValues rowData = to;
        Record record = Utils.convertToRecord(rowData);

        // to在数据中间有四种可能
        // data:5,6,7,8,9,10,15
        // case1: to是data的某个值，如9
        // case2: to大于最大值，如17
        // case3: to小于最小值，如2
        // case4: to在某两个值之间，如11
        // case5: data为空

        if (!cursor.skipTo(record)) {//to>游标中的last,to对应的值不存在找游标的最后一个。
            RowValues last = cursor.last();
            if (last == null) {
                return null;
            }
            if (match(last)) {
                return last;
            } else {
                return null;
            }
        } else {
            if (match(cursor.current())) {
                return cursor.current();
            } else {
                RowValues prevCurrent = cursor.prev();// 取prev有效值
                if (prevCurrent == null) {
                    return null;
                } else {
                    if (match(prevCurrent)) {
                        return prevCurrent;
                    } else {
                        return null;
                    }
                }
            }
        }
    }


    public String toString() {
        return toStringWithInden(0);
    }

    public String toStringWithInden(int inden) {
        StringBuilder sb = new StringBuilder();
        String tab = GeneralUtil.getTab(inden);
        sb.append(tab).append("【Range cursor .start : ").append(from).append("|").append(" end : ").append(to).append("\n");
        Utils.printOrderByList(orderByList, inden, sb);
        sb.append(super.toStringWithInden(inden));
        return sb.toString();
    }

    public void beforeFirst() throws RuntimeException {
        this.first = true;
    }


}
